/*
 * Copyright 2010    Sylvere RICHARD
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.infotrafficlux.server.service;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.appengine.api.urlfetch.FetchOptions;
import com.google.appengine.api.urlfetch.HTTPMethod;
import com.google.appengine.api.urlfetch.HTTPRequest;
import com.google.appengine.api.urlfetch.HTTPResponse;
import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.appengine.api.urlfetch.URLFetchServiceFactory;
import com.google.infotrafficlux.server.bean.Place;
import com.google.infotrafficlux.server.bean.Segment;
import com.google.infotrafficlux.server.bean.Segment.TrafficStatus;
import com.google.infotrafficlux.server.dao.PlaceDao;

@Service
public class SegmentServiceImpl implements SegmentService {

	private static final String URL_CITA = "http://www2.pch.etat.lu/info_trafic/niveau_service/niveau_service_convert.jsp";

	private PlaceDao placeDao;

	/**
	 * @return the placeDao
	 */
	public PlaceDao getPlaceDao() {
		return placeDao;
	}

	/**
	 * @param placeDao
	 *            the placeDao to set
	 */
	@Autowired
	public void setPlaceDao(PlaceDao placeDao) {
		this.placeDao = placeDao;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.google.infotrafficlux.server.service.SegmentService#getAllSegment()
	 */
	public List<Segment> getAllSegment() {

		try {
			final String result = fetchCitaUrl();

			return parseAsSegment(result);

		} catch (Exception e) {
			throw new RuntimeException(e);
		}

	}

	/**
	 * 
	 * @param result
	 * @return
	 */
	List<Segment> parseAsSegment(final String result) {
		final List<Segment> ret = new ArrayList<Segment>();
		final String regexp = "z(\\d\\d\\d\\d)_(\\d\\d\\d\\d)=(\\w+)";
		final Pattern urlPattern = Pattern.compile(regexp);
		for (String elt : result.split("&")) {
			String[] value = parseElement(urlPattern, elt);

			if(value == null) {
				continue;
			}
			
			final Place origin = getPlaceDao().findByCitaId(value[0]);
			if (origin == null) {
				continue;
			}
			final Place destination = getPlaceDao().findByCitaId(value[1]);
			if (destination == null) {
				continue;
			}

			final Segment s = new Segment();

			s.setOrigin(origin);
			s.setDestination(destination);
			s.setStatus(TrafficStatus.valueOf(value[2]));

			ret.add(s);
		}
		return ret;
	}

	private String[] parseElement(final Pattern urlPattern, String elt) {
		elt = elt.trim();
		Matcher matcher = urlPattern.matcher(elt);

		if (matcher.matches() == false) {
			return null;
		}
		String[] value = new String[3];
		for (int i = 1; i < matcher.groupCount() + 1; i++) {
			value[i - 1] = matcher.group(i);
		}
		return value;
	}

	/**
	 * 
	 * @return
	 * @throws MalformedURLException
	 * @throws IOException
	 */
	private String fetchCitaUrl() throws MalformedURLException, IOException {
		URL url = new URL(URL_CITA);

		FetchOptions options = FetchOptions.Builder.doNotFollowRedirects()
				.disallowTruncate();
		HTTPRequest request = new HTTPRequest(url, HTTPMethod.GET, options);

		URLFetchService service = URLFetchServiceFactory.getURLFetchService();
		HTTPResponse response = service.fetch(request);

		final String result = new String(response.getContent());
		return result;
	}
}
